home *** CD-ROM | disk | FTP | other *** search
/ InterCD 2000 September / september_2000.iso / intercd / root / ^Linux / WindowMaker / wrlib / png.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-03-09  |  5.4 KB  |  232 lines

  1. /* png.c - load PNG image from file
  2.  * 
  3.  *  Raster graphics library
  4.  * 
  5.  *  Copyright (c) 1997 Alfredo K. Kojima
  6.  *
  7.  *  This library is free software; you can redistribute it and/or
  8.  *  modify it under the terms of the GNU Library General Public
  9.  *  License as published by the Free Software Foundation; either
  10.  *  version 2 of the License, or (at your option) any later version.
  11.  *  
  12.  *  This library is distributed in the hope that it will be useful,
  13.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  15.  *  Library General Public License for more details.
  16.  *  
  17.  *  You should have received a copy of the GNU Library General Public
  18.  *  License along with this library; if not, write to the Free
  19.  *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20.  */
  21.  
  22. #include <config.h>
  23.  
  24. /* AIX requires this to be the first thing in the file.  */
  25. #ifdef __GNUC__
  26. # define alloca __builtin_alloca
  27. #else
  28. # if HAVE_ALLOCA_H
  29. #  include <alloca.h>
  30. # else
  31. #  ifdef _AIX
  32. #   pragma alloca
  33. #  else
  34. #   ifndef alloca /* predefined by HP cc +Olibcalls */
  35. char *alloca ();
  36. #   endif
  37. #  endif
  38. # endif
  39. #endif
  40.  
  41.  
  42. #ifdef USE_PNG
  43.  
  44. #include <stdlib.h>
  45. #include <stdio.h>
  46. #include <string.h>
  47.  
  48. #include <png.h>
  49.  
  50. #include "wraster.h"
  51.  
  52.  
  53. RImage*
  54. RLoadPNG(RContext *context, char *file, int index)
  55. {
  56.     char *tmp;
  57.     RImage *image=NULL;
  58.     FILE *f;
  59.     png_structp png;
  60.     png_infop pinfo, einfo;
  61.     png_color_16p bkcolor;
  62.     int alpha;
  63.     int x, y, i;
  64.     double gamma, sgamma;
  65.     png_uint_32 width, height;
  66.     int depth, junk, color_type;
  67.     png_bytep *png_rows;
  68.     unsigned char *ptr;
  69.     
  70.     f = fopen(file, "r");
  71.     if (!f) {
  72.     RErrorCode = RERR_OPEN;
  73.     return NULL;
  74.     }
  75.     png = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, 
  76.                  (png_error_ptr)NULL, (png_error_ptr)NULL);
  77.     if (!png) {
  78.     RErrorCode = RERR_NOMEMORY;
  79.     fclose(f);
  80.     return NULL;
  81.     }
  82.     
  83.     pinfo = png_create_info_struct(png);
  84.     if (!pinfo) {
  85.     RErrorCode = RERR_NOMEMORY;
  86.     fclose(f);
  87.     png_destroy_read_struct(&png, NULL, NULL);
  88.     return NULL;
  89.     }
  90.  
  91.     einfo = png_create_info_struct(png);
  92.     if (!einfo) {
  93.     RErrorCode = RERR_NOMEMORY;
  94.     fclose(f);
  95.     png_destroy_read_struct(&png, &pinfo, NULL);
  96.     return NULL;
  97.     }
  98.  
  99.     RErrorCode = RERR_INTERNAL;
  100.     if (setjmp(png->jmpbuf)) {
  101.     fclose(f);
  102.     png_destroy_read_struct(&png, &pinfo, &einfo);
  103.     if (image)
  104.       RDestroyImage(image);
  105.     return NULL;
  106.     }
  107.     
  108.     png_init_io(png, f);
  109.     
  110.     png_read_info(png, pinfo);
  111.     
  112.     png_get_IHDR(png, pinfo, &width, &height, &depth, &color_type,
  113.          &junk, &junk, &junk);
  114.  
  115.     
  116.     /* check for an alpha channel */
  117.     if (png_get_valid(png, pinfo, PNG_INFO_tRNS))
  118.       alpha = True;
  119.     else
  120.       alpha = (color_type & PNG_COLOR_MASK_ALPHA);
  121.  
  122.     /* allocate RImage */
  123.     image = RCreateImage(width, height, alpha);
  124.     if (!image) {
  125.     fclose(f);
  126.     png_destroy_read_struct(&png, &pinfo, &einfo);
  127.     return NULL;
  128.     }
  129.     
  130.     /* normalize to 8bpp with alpha channel */
  131.     if (color_type == PNG_COLOR_TYPE_PALETTE && depth <= 8)
  132.         png_set_expand(png);
  133.  
  134.     if (color_type == PNG_COLOR_TYPE_GRAY && depth <= 8)
  135.         png_set_expand(png);
  136.  
  137.     if (png_get_valid(png, pinfo, PNG_INFO_tRNS))
  138.         png_set_expand(png);
  139.  
  140.     if (depth == 16)
  141.         png_set_strip_16(png);
  142.  
  143.     if (color_type == PNG_COLOR_TYPE_GRAY ||
  144.         color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
  145.           png_set_gray_to_rgb(png);
  146.  
  147.     /* set gamma correction */
  148.     if ((context->attribs->flags & RC_GammaCorrection)
  149.     && context->depth != 8) {
  150.     sgamma = (context->attribs->rgamma + context->attribs->ggamma +
  151.           context->attribs->bgamma) / 3;
  152.     } else if ((tmp = getenv("DISPLAY_GAMMA")) != NULL) {
  153.     sgamma = atof(tmp);
  154.     if (sgamma==0)
  155.         sgamma = 1;
  156.     } else {
  157.     /* blah */
  158.     sgamma = 2.2;
  159.     }
  160.     
  161.     if (png_get_gAMA(png, pinfo, &gamma))
  162.       png_set_gamma(png, sgamma, gamma);
  163.     else
  164.       png_set_gamma(png, sgamma, 0.45);
  165.  
  166.     /* do the transforms */
  167.     png_read_update_info(png, pinfo);
  168.  
  169.     /* set background color */
  170.     if (png_get_bKGD(png, pinfo, &bkcolor)) {
  171.     image->background.red = bkcolor->red >> 8;
  172.     image->background.green = bkcolor->green >> 8;
  173.     image->background.blue = bkcolor->blue >> 8;
  174.     }
  175.  
  176.     png_rows = alloca(sizeof(char*)*height);
  177.     if (!png_rows) {
  178.     RErrorCode = RERR_NOMEMORY;
  179.     fclose(f);
  180.     RDestroyImage(image);
  181.     png_destroy_read_struct(&png, &pinfo, &einfo);
  182. #ifdef C_ALLOCA
  183.     alloca(0);
  184. #endif
  185.     return NULL;
  186.     }
  187.     for (y=0; y<height; y++) {
  188.     png_rows[y] = alloca(png_get_rowbytes(png, pinfo));
  189.     if (!png_rows[y]) {
  190.         RErrorCode = RERR_NOMEMORY;
  191.         fclose(f);
  192.         RDestroyImage(image);
  193.         png_destroy_read_struct(&png, &pinfo, &einfo);
  194. #ifdef C_ALLOCA
  195.         alloca(0);
  196. #endif
  197.         return NULL;
  198.     }
  199.     }
  200.     /* read data */
  201.     png_read_image(png, png_rows);
  202.     
  203.     png_read_end(png, einfo);
  204.     
  205.     png_destroy_read_struct(&png, &pinfo, &einfo);
  206.     
  207.     fclose(f);
  208.  
  209.     ptr = image->data;
  210.  
  211.     /* convert to RImage */
  212.     if (alpha) {
  213.     for (y=0; y<height; y++) {
  214.         for (x=0, i=width*4; x<i; x++, ptr++) {
  215.         *ptr = *(png_rows[y]+x);
  216.         }
  217.     }
  218.     } else {
  219.     for (y=0; y<height; y++) {
  220.         for (x=0, i=width*3; x<i; x++, ptr++) {
  221.         *ptr = *(png_rows[y]+x);
  222.         }
  223.     }    
  224.     }
  225. #ifdef C_ALLOCA
  226.     alloca(0);
  227. #endif
  228.     return image;
  229. }
  230.  
  231. #endif /* USE_PNG */
  232.